import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { MonitoringDataDto } from './dto';
import {
  PageVisitEntity,
  UserEventEntity,
  ErrorLogEntity,
  PerformanceMetricEntity,
  ApiRequestEntity,
  UserSessionEntity
} from './entities';

@Injectable()
export class MonitoringService {
  private readonly logger = new Logger(MonitoringService.name);

  constructor(
    @InjectRepository(PageVisitEntity)
    private readonly pageVisitRepository: Repository<PageVisitEntity>,
    
    @InjectRepository(UserEventEntity)
    private readonly userEventRepository: Repository<UserEventEntity>,
    
    @InjectRepository(ErrorLogEntity)
    private readonly errorLogRepository: Repository<ErrorLogEntity>,
    
    @InjectRepository(PerformanceMetricEntity)
    private readonly performanceMetricRepository: Repository<PerformanceMetricEntity>,
    
    @InjectRepository(ApiRequestEntity)
    private readonly apiRequestRepository: Repository<ApiRequestEntity>,
    
    @InjectRepository(UserSessionEntity)
    private readonly userSessionRepository: Repository<UserSessionEntity>
  ) {}

  /**
   * 保存单条监控数据
   * @param data 监控数据
   */
  async saveMonitoringData(data: MonitoringDataDto): Promise<void> {
    const { type } = data;

    switch (type) {
      case 'page_view':
        await this.savePageVisit(data);
        break;
      case 'event':
        await this.saveUserEvent(data);
        break;
      case 'error':
        await this.saveErrorLog(data);
        break;
      case 'performance':
        await this.savePerformanceMetric(data);
        break;
      case 'api_request':
        await this.saveApiRequest(data);
        break;
      default:
        this.logger.warn(`未知的监控数据类型: ${type}`);
    }
  }

  /**
   * 批量保存监控数据
   * @param dataList 监控数据列表
   */
  async saveBatchMonitoringData(dataList: MonitoringDataDto[]): Promise<void> {
    for (const data of dataList) {
      try {
        await this.saveMonitoringData(data);
      } catch (error) {
        this.logger.error(`保存单条监控数据失败: ${error.message}`, error.stack);
      }
    }
  }

  /**
   * 保存页面访问记录
   * @param data 页面访问数据
   */
  private async savePageVisit(data: MonitoringDataDto): Promise<void> {
    const pageVisit = this.pageVisitRepository.create({
      userId: data.userId,
      pageUrl: data.pageUrl,
      pageTitle: data.pageTitle,
      referrer: data.referrer,
      browser: data.browser,
      os: data.os,
      ipAddress: data.ipAddress,
      userAgent: data.userAgent,
      visitTime: new Date()
    });

    await this.pageVisitRepository.save(pageVisit);
  }

  /**
   * 保存用户事件
   * @param data 用户事件数据
   */
  private async saveUserEvent(data: MonitoringDataDto): Promise<void> {
    const userEvent = this.userEventRepository.create({
      userId: data.userId,
      eventType: data.eventType,
      elementText: data.elementText,
      elementClass: data.elementClass,
      elementId: data.elementId,
      eventData: JSON.stringify({
        elementTag: data.elementTag,
        xCoordinate: data.xCoordinate,
        yCoordinate: data.yCoordinate
      }),
      pageUrl: data.pageUrl,
      browser: data.browser,
      os: data.os,
      ipAddress: data.ipAddress,
      userAgent: data.userAgent,
      eventTime: new Date()
    });

    await this.userEventRepository.save(userEvent);
  }

  /**
   * 保存错误日志
   * @param data 错误日志数据
   */
  private async saveErrorLog(data: MonitoringDataDto): Promise<void> {
    const errorLog = this.errorLogRepository.create({
      userId: data.userId,
      errorType: data.errorType,
      errorMessage: data.errorMessage,
      errorStack: data.errorStack,
      pageUrl: data.pageUrl,
      browser: data.browser,
      os: data.os,
      ipAddress: data.ipAddress,
      userAgent: data.userAgent,
      occurredAt: new Date()
    });

    await this.errorLogRepository.save(errorLog);
  }

  /**
   * 保存性能指标
   * @param data 性能指标数据
   */
  private async savePerformanceMetric(data: MonitoringDataDto): Promise<void> {
    const performance = data.performance || {};
    
    const performanceMetric = this.performanceMetricRepository.create({
      userId: data.userId,
      pageUrl: data.pageUrl,
      pageTitle: data.pageTitle,
      navigationStart: performance.navigationStart,
      unloadEventStart: performance.unloadEventStart,
      unloadEventEnd: performance.unloadEventEnd,
      redirectStart: performance.redirectStart,
      redirectEnd: performance.redirectEnd,
      fetchStart: performance.fetchStart,
      domainLookupStart: performance.domainLookupStart,
      domainLookupEnd: performance.domainLookupEnd,
      connectStart: performance.connectStart,
      connectEnd: performance.connectEnd,
      secureConnectionStart: performance.secureConnectionStart,
      requestStart: performance.requestStart,
      responseStart: performance.responseStart,
      responseEnd: performance.responseEnd,
      domLoading: performance.domLoading,
      domInteractive: performance.domInteractive,
      domContentLoadedEventStart: performance.domContentLoadedEventStart,
      domContentLoadedEventEnd: performance.domContentLoadedEventEnd,
      domComplete: performance.domComplete,
      loadEventStart: performance.loadEventStart,
      loadEventEnd: performance.loadEventEnd,
      firstPaint: performance.firstPaint,
      firstContentfulPaint: performance.firstContentfulPaint,
      largestContentfulPaint: performance.largestContentfulPaint,
      firstInputDelay: performance.firstInputDelay,
      cumulativeLayoutShift: performance.cumulativeLayoutShift,
      browser: data.browser,
      os: data.os,
      ipAddress: data.ipAddress,
      userAgent: data.userAgent,
      measuredAt: new Date()
    });

    await this.performanceMetricRepository.save(performanceMetric);
  }

  /**
   * 保存API请求记录
   * @param data API请求数据
   */
  private async saveApiRequest(data: MonitoringDataDto): Promise<void> {
    const apiRequest = this.apiRequestRepository.create({
      userId: data.userId,
      apiUrl: data.apiUrl,
      method: data.httpMethod,
      statusCode: data.statusCode,
      responseTime: data.duration,
      requestTime: new Date()
    });

    await this.apiRequestRepository.save(apiRequest);
  }

  /**
   * 获取页面访问统计
   * @param query 查询参数
   */
  async getPageVisitStats(query?: any): Promise<any> {
    const { startDate, endDate, userId } = query || {};
    
    const queryBuilder = this.pageVisitRepository.createQueryBuilder('page_visit');
    
    if (startDate) {
      queryBuilder.andWhere('page_visit.visitTime >= :startDate', { startDate });
    }
    
    if (endDate) {
      queryBuilder.andWhere('page_visit.visitTime <= :endDate', { endDate });
    }
    
    if (userId) {
      queryBuilder.andWhere('page_visit.userId = :userId', { userId });
    }

    const totalVisits = await queryBuilder.getCount();
    
    // 今日访问统计
    const todayQuery = this.pageVisitRepository
      .createQueryBuilder('page_visit')
      .where('DATE(page_visit.visitTime) = DATE(NOW())');
    
    if (userId) {
      todayQuery.andWhere('page_visit.userId = :userId', { userId });
    }
    
    const todayVisits = await todayQuery.getCount();

    // 本周访问统计
    const weekQuery = this.pageVisitRepository
      .createQueryBuilder('page_visit')
      .where('page_visit.visitTime >= DATE_SUB(NOW(), INTERVAL 7 DAY)');
    
    if (userId) {
      weekQuery.andWhere('page_visit.userId = :userId', { userId });
    }
    
    const weekVisits = await weekQuery.getCount();

    return {
      totalVisits,
      todayVisits,
      weekVisits
    };
  }

  /**
   * 获取错误统计
   * @param query 查询参数
   */
  async getErrorStats(query?: any): Promise<any> {
    const { startDate, endDate, userId } = query || {};
    
    const queryBuilder = this.errorLogRepository.createQueryBuilder('error_log');
    
    if (startDate) {
      queryBuilder.andWhere('error_log.occurredAt >= :startDate', { startDate });
    }
    
    if (endDate) {
      queryBuilder.andWhere('error_log.occurredAt <= :endDate', { endDate });
    }
    
    if (userId) {
      queryBuilder.andWhere('error_log.userId = :userId', { userId });
    }

    const totalErrors = await queryBuilder.getCount();
    
    // 今日错误统计
    const todayQuery = this.errorLogRepository
      .createQueryBuilder('error_log')
      .where('DATE(error_log.occurredAt) = DATE(NOW())');
    
    if (userId) {
      todayQuery.andWhere('error_log.userId = :userId', { userId });
    }
    
    const todayErrors = await todayQuery.getCount();

    // 错误类型统计
    const errorTypeStats = await this.errorLogRepository
      .createQueryBuilder('error_log')
      .select('error_log.errorType', 'type')
      .addSelect('COUNT(*)', 'count')
      .groupBy('error_log.errorType')
      .orderBy('count', 'DESC')
      .limit(10)
      .getRawMany();

    return {
      totalErrors,
      todayErrors,
      errorTypeStats
    };
  }
}